/*
程序运行,内存测试。

$ gcc -std=c11 -O0 main.c
$ ./a.out -b 1024 -s 8

-b 内存大小，字节，默认1024
-s 计算开始数值，随便写，默认500
-l 初始计算，然后接受用户的输入，输入0就退出

*/
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>

struct memory_space {
    unsigned long long _space_size_byte;
    char* _space_pointer;
};

bool memory_space_init(struct memory_space* space_struct, unsigned long long sizeof_space) {
    space_struct->_space_size_byte = sizeof_space;
    space_struct->_space_pointer = (char*)calloc(sizeof_space, sizeof(char));
    return (void*)0 != space_struct->_space_pointer;
}

void memory_space_free(struct memory_space* space_struct) {
    if ((void*)0 != space_struct->_space_pointer) {
        free(space_struct->_space_pointer);
        space_struct->_space_pointer = (void*)0;
    }
}

unsigned long long memory_space_calc(struct memory_space* space_struct, int start_value) {
    if ((void*)0 == space_struct->_space_pointer) {
        return 0;
    }
    unsigned long long result = 0;
    space_struct->_space_pointer[0] = (char)start_value;
    for (unsigned long long i = 1; i < space_struct->_space_size_byte; i++) {
        if ((int)(space_struct->_space_pointer[i]) > 0) {
            space_struct->_space_pointer[i] = (char)(start_value * (int)(space_struct->_space_pointer[i]) + 1);
        } else {
            space_struct->_space_pointer[i] = (char)(-1 * start_value * (int)(space_struct->_space_pointer[i]) - 2);
        }
    }
    for (unsigned long long i = 0; i < space_struct->_space_size_byte; i++) {
        result += (unsigned long long)(space_struct->_space_pointer[i]);
    }
    return result;
}

int main(int argc, char *argv[]) {
    struct timespec start_time, end_time;

    FILE *fp;
    char file[10] = {'\0'};
    pid_t pid = getpid();
    unsigned int id = (int)pid;

    unsigned long long calc_result;
    unsigned long long byte_space_size = 1024;
    int start_value = 500;
    struct memory_space test_space;
    bool keep = false;
    int tmp = 0;
    for (int i = 0; i < argc; i++) {
        if (0 == strcmp(argv[i], "-b")) {
            tmp = 1;
            continue;
        }
        if (0 == strcmp(argv[i], "-s")) {
            tmp = 2;
            continue;
        }
        if (0 == strcmp(argv[i], "-l")) {
            keep = true;
        }
        switch (tmp) {
        case 1:
            byte_space_size = strtoull(argv[i], NULL, 0);
            tmp = 0;
            break;
        case 2:
            start_value = atoi(argv[i]);
            tmp = 0;
            break;
        default:;
        }
    }

    sprintf(file, "%d.txt", pid);
    fp = fopen(file, "w");
    if (NULL == fp) {
        fprintf(stderr, "[ERROR] (%d) FAIL, can not open file \"%s\"\n", id, file);
        return 1;
    }

    fprintf(fp, "[INFO] (%d) %ld bytes start_value=%d\n", id, byte_space_size, start_value);
    timespec_get(&start_time, TIME_UTC);
    bool is_ok = memory_space_init(&test_space, byte_space_size);
    timespec_get(&end_time, TIME_UTC);
    fprintf(fp, "[INFO] (%d) memory_space_init %.9lf sec\n", id, difftime(end_time.tv_sec, start_time.tv_sec) + (double)(end_time.tv_nsec - start_time.tv_nsec) / 1000000000.0);

    int res = 0;
    if (is_ok) {
        timespec_get(&start_time, TIME_UTC);
        calc_result = memory_space_calc(&test_space, start_value);
        timespec_get(&end_time, TIME_UTC);
        fprintf(fp, "[INFO] (%d) memory_space_calc %.9lf sec\n", id, difftime(end_time.tv_sec, start_time.tv_sec) + (double)(end_time.tv_nsec - start_time.tv_nsec) / 1000000000.0);
        fprintf(fp, "[INFO] (%d) SUCCESS result=%ld\n", id, calc_result);
        while (true) {
            if (!keep) {
                break;
            }
            scanf("%d", &res);
            if (0 == res) {
                break;
            }
        }
        memory_space_free(&test_space);
    } else {
        fprintf(fp, "[ERROR] (%d) FAIL\n", id);
        res = 2;
    }
    fclose(fp);
    return res;
}


